package com.heima.wemedia.service.inpl;

import com.alibaba.fastjson.JSONArray;
import com.heima.aliyun.GreenImageScan;
import com.heima.aliyun.GreenTextScan;
import com.heima.common.exception.CustException;
import com.heima.feigns.admin.AdminFeign;
import com.heima.model.admin.dtos.ResponseResult;
import com.heima.model.admin.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.service.WmNewsAutoScanService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.json.JsonArray;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class WmNewsAutoScanServiceImpl implements WmNewsAutoScanService {
    @Autowired
    private WmNewsMapper wmNewsMapper;
    @Value("${file.oss.web-site}")
    String webSite;

    /**
     * 自动审核方法
     * @param wmNewsId   自媒体文章id
     */
    @Override
    public void aotoScanWmNews(Integer wmNewsId) {
        log.info("自动审核发布方法 被调用 当前审核发布的文章id==>{}",wmNewsId);
        // 根据文章id  远程调用feign查询文章
        if(wmNewsId==null){
            log.error("自动审核文章失败  文章id为空");
            CustException.cust(AppHttpCodeEnum.PARAM_INVALID);
        }
        WmNews wmNews = wmNewsMapper.selectById(wmNewsId);
        if(wmNews==null){
            log.error("自动审核文章失败  未查询到自媒体文章信息 wmNewsId:{}",wmNews);
            CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //2: 判断文章状态是否为待审核状态
        Short status = wmNews.getStatus();
        if(status.shortValue()==WmNews.Status.SUBMIT.getCode()){
            //抽取出文章内容  所有的文本内容 和 所有的图片url集合  map<String,Object> content 内容 imagesList<String>
            Map<String,Object> contentAndImageResult=handleTextAndImages(wmNews);
            //3.1 敏感词审核  失败  修改文章状态(2)
          boolean isSensivice=handleSensitive((String)contentAndImageResult.get("content"),wmNews);
          if(!isSensivice) {
              return;
          }
          log.info("自管理敏感词审核通过  =======");
          //3.2 阿里云的文本审核  失败  状态2  不确定  状态3
          boolean isTextScan= handelTextScan((String)contentAndImageResult.get("content"),wmNews);
          if(!isTextScan){
              return;
          }
          log.info("阿里云内容审核通过======");

          //3.3  阿里云的图片审核  失败 状态2 不确定 状态3
            Object images = contentAndImageResult.get("images");
            if(images!=null){
                boolean isImageScan=handelImageScan((List<String>)images,wmNews);
                if(!isImageScan){
                    return;
                }
                log.info("阿里云图片审核通过=====");
            }
            //4: 判断文章发布时间是否大于当前时间   状态8
            updateWmNews(wmNews,WmNews.Status.SUCCESS.getCode(),"审核成功");

            //TODO: 5  通知定时发布文章

        }
    }
            @Autowired
    GreenImageScan greenImageScan;

    /**
     * 阿里云图片审核
     * @param images 待审核的图片列表
     * @param wmNews  文章
     * @return
     */
    private boolean handelImageScan(List<String> images, WmNews wmNews) {
        boolean flag=true;
        try {
            Map map = greenImageScan.imageUrlScan(images);

            String suggestion = (String) map.get("suggestion");
            switch (suggestion){
                case "block":
                    updateWmNews(wmNews,WmNews.Status.FAIL.getCode(),"图片中有违规内容,审核失败");
                    flag=false;
                    break;
                case "review":
                    updateWmNews(wmNews,WmNews.Status.ADMIN_AUTH.getCode(),"图片中有不确定内容,转为人工审核");
                    flag=false;
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("阿里云图片审核出现异常,原因:{}",e.getMessage());
            updateWmNews(wmNews,WmNews.Status.ADMIN_AUTH.getCode(),"阿里云内容服务异常,转为人工审核");
            flag=false;
        }
        return flag;
    }


    /**
     * 阿里云文本
     * @param content block: 状态2 review:状态3   异常: 状态3
     * @param wmNews
     * @return
     */
    @Autowired
    GreenTextScan greenTextScan;
    private boolean handelTextScan(String content, WmNews wmNews) {
        boolean flag=true;
        try {
            Map map = greenTextScan.greenTextScan(content);
            String suggestion = (String) map.get("suggestion");
            switch (suggestion){
                case "block":
                    updateWmNews(wmNews,WmNews.Status.FAIL.getCode(),"文本有违规内容,审核失败");
                    flag=false;
                    break;
                case "review":
                    updateWmNews(wmNews,WmNews.Status.ADMIN_AUTH.getCode(),"文本中有不确定内容,转为人工审核");
                    flag=false;
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("阿里云文本审核出现异常,原因 {}",e.getMessage());
            updateWmNews(wmNews,WmNews.Status.ADMIN_AUTH.getCode(),"阿里云内容服务异常,转为人工审核");
            flag=false;
        }
        return flag;
    }


    /**
     *基于DFA  检查内容是否包含敏感词
     * @param content
     * @param wmNews
     * @return
     */
    @Autowired
    AdminFeign adminFeign;
    private boolean handleSensitive(String content, WmNews wmNews) {
        boolean flag=true;
        //1: 查询出数据库中的敏感词
        ResponseResult<List<String>> allSensitivesResult=adminFeign.sensitives();
        if(allSensitivesResult.getCode().intValue()!=0){
            CustException.cust(AppHttpCodeEnum.REMOTE_SERVER_ERROR,allSensitivesResult.getErrorMessage());
        }
        List<String> allSensitives = allSensitivesResult.getData();
        // 2 将敏感词集合转发DFN数据模型
        SensitiveWordUtil.initMap(allSensitives);
        //3:检测敏感词
        Map<String, Integer> resultMap = SensitiveWordUtil.matchWords(content);
        if(resultMap!=null && resultMap.size()>0){
            //将文章状态改为2
            updateWmNews(wmNews,WmNews.Status.FAIL.getCode(),"内容中包含敏感词:"+resultMap);
            flag=false;
        }
        return flag;
    }





    /**
     * 修改文章状态
     * @param wmNews
     * @param  status
     * @param reason
     */

    private void updateWmNews(WmNews wmNews, short status, String reason) {
        wmNews.setStatus(status);
        wmNews.setReason(reason);
        wmNewsMapper.updateById(wmNews);
    }




    /**
     *抽取  文章中所有  文本内容 及 所有图片路径
     * @param wmNews content type:text  title
     * @return
     */
    private Map<String, Object> handleTextAndImages(WmNews wmNews) {
        String contentJson = wmNews.getContent();  //{} {} {}
        if(StringUtils.isBlank(contentJson)){
            log.error("自动审核文章失败  文章内容为空");
            CustException.cust(AppHttpCodeEnum.PARAM_INVALID,"文章内容为空");
        }
        List<Map> contentMaps = JSONArray.parseArray(contentJson, Map.class);
        //1: 抽取文章中所有文本  家乡很美  _hmtt_ 国家伟大
        String content = contentMaps.stream()
                .filter(map -> "text".equals(map.get("type")))
                .map(map -> (String) map.get("value"))
                .collect(Collectors.joining("_hmtt_"));

        content=content+"_hmtt_"+wmNews.getTitle();

        //2: 抽取文章中所有图片  content: 全路径  images: 文件名称 + 访问前缀
        List<String> imageList = contentMaps.stream()
                .filter(map -> "image".equals(map.get("type")))
                .map(map -> (String) map.get("value"))
                .collect(Collectors.toList());
        if(StringUtils.isNotBlank(wmNews.getImages())){
            //按照 逗号  切割封面字符串  得到数组  基于数组得到stream  将每一条数据都拼接一个前缀  手机成集合
            List<String> urls = Arrays.stream(wmNews.getImages().split(","))
                    .map(url -> webSite + url)
                    .collect(Collectors.toList());
            imageList.addAll(urls);

        }
        //3  去重
        imageList = imageList.stream().distinct().collect(Collectors.toList());
        Map result=new HashMap();
        result.put("content",content);
        result.put("images",imageList);
        return  result;
    }
                //此类没有经过测试
}
